package com.cyh.testcoroutine

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.View
import kotlinx.android.synthetic.main.activity_main.*
import kotlinx.coroutines.*
import kotlinx.coroutines.channels.*
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import java.io.IOException
import java.util.concurrent.atomic.AtomicInteger
import kotlin.system.measureTimeMillis

/**
 * launch - 创建协程
async - 创建带返回值的协程，返回的是 Deferred 类
withContext - 不创建新的协程，在指定协程上运行代码块
runBlocking - 不是 GlobalScope 的 API，可以独立使用，区别是 runBlocking 里面的 delay 会阻塞线程，而 launch 创建的不会


launch 是个扩展函数，接受3个参数，前面2个是常规参数，最后一个是个对象式函数
    第一个参数 CoroutineContext - 可以理解为协程的上下文，有 4种线程模式：不写的话就是 Dispatchers.Default 模式的
            Dispatchers.Default - 线程池中的线程
            Dispatchers.IO - io线程
            Dispatchers.Main - 主线程
            Dispatchers.Unconfined - 没指定，就是在当前线程
    第二个参数 CoroutineStart - 启动模式，默认是DEAFAULT，也就是创建就启动；还有一个是LAZY，意思是等你需要它的时候，再调用启动
            DEAFAULT - 模式模式，不写就是默认
            ATOMIC -
            UNDISPATCHED
            LAZY - 懒加载模式，你需要它的时候，再调用启动 看onClickTest9

job.start() - 启动协程，除了 lazy 模式，协程都不需要手动启动
job.join() - 等待协程执行完毕
job.cancel() - 取消一个协程
job.cancelAndJoin() - 等待协程执行完毕然后再取消

runBlocking 和 launch 区别的地方就是 runBlocking 的 delay 方法是可以阻塞当前的线程的，和Thread.sleep() 一样

协程和 thread 最大的不同，thread 线程之间采取的是竞争 cpu 时间段的方法，谁抢到谁运行，由系统内核控制，对我们来说是不可见不可控的。
协程不同，协程之间不用竞争、谁运行、谁挂起、什么时候恢复都是由我们自己控制的


suspend 函数会将整个协程挂起，而不仅仅是这个 suspend 函数


在概念上，async 就类似于 launch。它启动了一个单独的协程，这是一个轻量级的线程并与其它所有的协程一起并发的工作。
不同之处在于 launch 返回一个 Job 并且不附带任何结果值，而 async 返回一个 Deferred —— 一个轻量级的非阻塞 future，
这代表了一个将会在稍后提供结果的 promise。你可以使用 .await() 在一个延期的值上得到它的最终结果，
但是 Deferred 也是一个 Job，所以如果需要的话，你可以取消它。
 */
class MainActivity : AppCompatActivity() {
    private val TAG : String = "Coroutine"
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    fun onClickTest1(view: View){
        GlobalScope.launch {
            Log.i(TAG, "--2--${Thread.currentThread().name}")
            delay(200L) //只能在协程中使用
            //this@MainActivity.tv_test.text = "222" //报错，因为不是主线程
            Log.i(TAG, "--4--${Thread.currentThread().name}")
        }
        Log.i(TAG, "--1--${Thread.currentThread().name}")
        Thread.sleep(100L)
        Log.i(TAG, "--3--${Thread.currentThread().name}")
    }
    fun onClickTest2(view: View){
        GlobalScope.launch {
            Log.i(TAG, "--2--${Thread.currentThread().name}")
            delay(100L) //只能在协程中使用
            Log.i(TAG, "--4--${Thread.currentThread().name}")
        }
        Log.i(TAG, "--1--${Thread.currentThread().name}")
        runBlocking { //表达式阻塞了当前线程
            Log.i(TAG, "--3--${Thread.currentThread().name}")
            delay(200L)
            Log.i(TAG, "--5--${Thread.currentThread().name}")
        }
        Log.i(TAG, "--6--${Thread.currentThread().name}")

    }
    fun onClickTest3(view: View){
        Log.i(TAG, "--1--${Thread.currentThread().name}")
        runBlocking<Unit> { // 开始执行主协程
            Log.i(TAG, "--2--${Thread.currentThread().name}")
            GlobalScope.launch { // 在后台启动一个新的协程并继续
                Log.i(TAG, "--4--${Thread.currentThread().name}")
                delay(100L)
                Log.i(TAG, "--5--${Thread.currentThread().name}")
            }
            Log.i(TAG, "--3--${Thread.currentThread().name}") // 主协程在这里会立即执行
            delay(200L)      // 延迟 2 秒来保证 JVM 存活
            Log.i(TAG, "--6--${Thread.currentThread().name}")
        }
    }
    fun onClickTest4(view: View){
        runBlocking<Unit> {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            val job = GlobalScope.launch { // 启动一个新协程并保持对这个作业的引用
                Log.i(TAG, "--3--${Thread.currentThread().name}")
                delay(100L)
                Log.i(TAG, "--4--${Thread.currentThread().name}")
            }

            Log.i(TAG, "--2--${Thread.currentThread().name}")
            job.join() // 等待直到子协程执行结束
            Log.i(TAG, "--5--${Thread.currentThread().name}")
        }
    }
    fun onClickTest5(view: View){
        runBlocking { // this: CoroutineScope
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            launch { // 在 runBlocking 作用域中启动一个新协程
                Log.i(TAG, "--3--${Thread.currentThread().name}")
                delay(100L)
                Log.i(TAG, "--4--${Thread.currentThread().name}")
            }
            Log.i(TAG, "--2--${Thread.currentThread().name}")
        }
    }
    fun onClickTest6(view: View){
        runBlocking { // this: CoroutineScope
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            launch {
                Log.i(TAG, "--5--${Thread.currentThread().name}")
                delay(200L)
                Log.i(TAG, "--8--${Thread.currentThread().name}")
            }
            Log.i(TAG, "--2--${Thread.currentThread().name}")
            coroutineScope { // 创建一个协程作用域
                Log.i(TAG, "--3--${Thread.currentThread().name}")
                launch {
                    Log.i(TAG, "--6--${Thread.currentThread().name}")
                    delay(500L)
                    Log.i(TAG, "--9--${Thread.currentThread().name}")
                }
                Log.i(TAG, "--4--${Thread.currentThread().name}")
                delay(100L)
                Log.i(TAG, "--7--${Thread.currentThread().name}") // 这一行会在内嵌 launch 之前输出
            }

            Log.i(TAG, "--10--${Thread.currentThread().name}") // 这一行在内嵌 launch 执行完毕后才输出
        }
    }
    fun onClickTest7(view: View){
        runBlocking {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            launch {
                Log.i(TAG, "--3--${Thread.currentThread().name}")
                doTest7_1();
                Log.i(TAG, "--5--${Thread.currentThread().name}")
                doTest7()
                Log.i(TAG, "--8--${Thread.currentThread().name}")
            }
            Log.i(TAG, "--2--${Thread.currentThread().name}")
        }
    }
    fun doTest7_1() {
        Log.i(TAG, "--4--${Thread.currentThread().name}")
    }
    // 这是你的第一个挂起函数
    suspend fun doTest7() {
        Log.i(TAG, "--6--${Thread.currentThread().name}")
        delay(100L)
        Log.i(TAG, "--7--${Thread.currentThread().name}")
    }
    fun onClickTest8(view: View){
        runBlocking {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            GlobalScope.launch {
                Log.i(TAG, "--3--${Thread.currentThread().name}")
                repeat(1000) { i ->
                    Log.i(TAG, "--4--$i--${Thread.currentThread().name}")
                    delay(500L)
                }
            }
            Log.i(TAG, "--2--${Thread.currentThread().name}")
            delay(1300L) // 在延迟后退出
            Log.i(TAG, "--5--${Thread.currentThread().name}")
        }
    }
    fun onClickTest9(view: View){
        runBlocking {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            var job:Job = GlobalScope.launch( start = CoroutineStart.LAZY ){
                Log.i(TAG, "--5--${Thread.currentThread().name}")
            }
            Log.i(TAG, "--2--${Thread.currentThread().name}")
            Thread.sleep( 100L )
            Log.i(TAG, "--3--${Thread.currentThread().name}")
            // 手动启动协程
            job.start()
            Log.i(TAG, "--4--${Thread.currentThread().name}")
        }
    }
    fun onClickTest10(view: View){
        GlobalScope.launch(Dispatchers.Unconfined) {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            val deferred = GlobalScope.async{
                Log.i(TAG, "--3--${Thread.currentThread().name}")
                delay(100L)
                Log.i(TAG, "--5--${Thread.currentThread().name}")
                return@async "协程返回值"
            }

            Log.i(TAG, "--2--${Thread.currentThread().name}")
            val result = deferred.await()
            Log.i(TAG, "--6--$result--${Thread.currentThread().name}")
        }

        Log.i(TAG, "--4--${Thread.currentThread().name}")
    }
    fun onClickTest11(view: View){
        GlobalScope.launch(Dispatchers.Unconfined) {
            for (i in 1..6) {
                Log.i(TAG, "--1--$i--${Thread.currentThread().name}")
            }
        }

        for (i in 1..8) {
            Log.i(TAG, "--2--$i--${Thread.currentThread().name}")
        }
    }
    fun onClickTest12(view: View){
        runBlocking {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            val job = launch {
                Log.i(TAG, "--3--${Thread.currentThread().name}")
                repeat(1000) { i ->
                    Log.i(TAG, "--4--$i--${Thread.currentThread().name}")
                    delay(500L)
                    Log.i(TAG, "--5--$i--${Thread.currentThread().name}")
                }
            }
            Log.i(TAG, "--2--${Thread.currentThread().name}")
            delay(1300L) // 延迟一段时间
            Log.i(TAG, "--6--${Thread.currentThread().name}")
            job.cancel() // 取消该作业
            Log.i(TAG, "--7--${Thread.currentThread().name}")
            job.join() // 等待作业执行结束
            Log.i(TAG, "--8--${Thread.currentThread().name}")
        }
    }
    fun onClickTest13(view: View){
        runBlocking {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            val startTime = System.currentTimeMillis()
            val job = launch(Dispatchers.Default) {
                Log.i(TAG, "--3--${Thread.currentThread().name}")
                var nextPrintTime = startTime
                var i = 0
                while (i < 5) { // 一个执行计算的循环，只是为了占用 CPU
                    // 每秒打印消息两次
                    if (System.currentTimeMillis() >= nextPrintTime) {
                        Log.i(TAG, "--4--${i++}--${Thread.currentThread().name}")
                        nextPrintTime += 500L
                    }
                }
            }
            Log.i(TAG, "--2--${Thread.currentThread().name}")
            delay(1300L) // 等待一段时间
            Log.i(TAG, "--5--${Thread.currentThread().name}")
            job.cancelAndJoin() // 取消一个作业并且等待它结束
            Log.i(TAG, "--6--${Thread.currentThread().name}")
        }
    }
    fun onClickTest14(view: View){
        runBlocking {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            val startTime = System.currentTimeMillis()
            val job = launch(Dispatchers.Default) {
                Log.i(TAG, "--3--${Thread.currentThread().name}")
                var nextPrintTime = startTime
                var i = 0
                while (isActive) { // 可以被取消的计算循环
                    // 每秒打印消息两次
                    if (System.currentTimeMillis() >= nextPrintTime) {
                        Log.i(TAG, "--4--${i++}--${Thread.currentThread().name}")
                        nextPrintTime += 500L
                    }
                }
            }
            Log.i(TAG, "--2--${Thread.currentThread().name}")
            delay(1300L) // 等待一段时间
            Log.i(TAG, "--5--${Thread.currentThread().name}")
            job.cancelAndJoin() // 取消该作业并等待它结束
            Log.i(TAG, "--6--${Thread.currentThread().name}")
        }
    }
    fun onClickTest15(view: View){
        runBlocking {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            val job = launch {
                try {
                    repeat(10) { i ->
                        Log.i(TAG, "--3--${i}--${Thread.currentThread().name}")
                        delay(500L)
                    }
                } finally {
                    Log.i(TAG, "--5--${Thread.currentThread().name}")
                }
            }
            Log.i(TAG, "--2--${Thread.currentThread().name}")
            delay(1300L) // 延迟一段时间
            Log.i(TAG, "--4--${Thread.currentThread().name}")
            job.cancelAndJoin() // 取消该作业并且等待它结束
            Log.i(TAG, "--6--${Thread.currentThread().name}")
        }
    }
    fun onClickTest16(view: View){
        runBlocking {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            val job = launch {
                try {
                    repeat(10) { i ->
                        Log.i(TAG, "--3--$i--${Thread.currentThread().name}")
                        delay(500L)
                    }
                } finally {
                    Log.i(TAG, "--5--${Thread.currentThread().name}")
                    withContext(NonCancellable) {
                        Log.i(TAG, "--6--${Thread.currentThread().name}")
                        delay(100L)
                        Log.i(TAG, "--7--${Thread.currentThread().name}")
                    }
                }
            }
            Log.i(TAG, "--2--${Thread.currentThread().name}")
            delay(1300L) // 延迟一段时间
            Log.i(TAG, "--4--${Thread.currentThread().name}")
            job.cancelAndJoin() // 取消该作业并等待它结束
            Log.i(TAG, "--8--${Thread.currentThread().name}")
        }
    }
    fun onClickTest17(view: View){
        runBlocking {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            withTimeout(1300L) {
                Log.i(TAG, "--2--${Thread.currentThread().name}")
                repeat(1000) { i ->
                    Log.i(TAG, "--3--${i}--${Thread.currentThread().name}")
                    delay(500L)
                }
            }
            Log.i(TAG, "--4--${Thread.currentThread().name}")
        }
    }
    fun onClickTest18(view: View){
        runBlocking {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            val result = withTimeoutOrNull(1300L) {
                Log.i(TAG, "--2--${Thread.currentThread().name}")
                repeat(100) { i ->
                    Log.i(TAG, "--3--${i}--${Thread.currentThread().name}")
                    delay(500L)
                }
                "Done" // 在它运行得到结果之前取消它
            }
            Log.i(TAG, "--4--${result}--${Thread.currentThread().name}") //result为null, 将repeat(1)则result为Done
        }
    }
    fun onClickTest19(view: View){
        runBlocking<Unit> {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            val time = measureTimeMillis {
                Log.i(TAG, "--2--${Thread.currentThread().name}")
                val one = test19_1()
                Log.i(TAG, "--5--${Thread.currentThread().name}")
                val two = test19_2() //顺序执行
                Log.i(TAG, "--8--${one + two}--${Thread.currentThread().name}")
            }
            Log.i(TAG, "--9--$time ms--${Thread.currentThread().name}")
        }
    }
    suspend fun test19_1(): Int {
        Log.i(TAG, "--3--${Thread.currentThread().name}")
        delay(1000L) // 假设我们在这里做了些有用的事
        Log.i(TAG, "--4--${Thread.currentThread().name}")
        return 13
    }

    suspend fun test19_2(): Int {
        Log.i(TAG, "--6--${Thread.currentThread().name}")
        delay(1000L) // 假设我们在这里也做了一些有用的事
        Log.i(TAG, "--7--${Thread.currentThread().name}")
        return 29
    }
    fun onClickTest20(view: View){
        runBlocking<Unit> {
            val time = measureTimeMillis {
                Log.i(TAG, "--1--${Thread.currentThread().name}")
                val one = async { test20_1() }
                val two = async { test20_2() }
                Log.i(TAG, "--2--${Thread.currentThread().name}")
                Log.i(TAG, "--7--${one.await() + two.await()}--${Thread.currentThread().name}") //并发执行
            }
            Log.i(TAG, "--8--$time ms--${Thread.currentThread().name}")
        }
    }

    suspend fun test20_1(): Int {
        Log.i(TAG, "--3--${Thread.currentThread().name}")
        delay(1000L) // 假设我们在这里做了些有用的事
        Log.i(TAG, "--5--${Thread.currentThread().name}")
        return 13
    }

    suspend fun test20_2(): Int {
        Log.i(TAG, "--4--${Thread.currentThread().name}")
        delay(1000L) // 假设我们在这里也做了一些有用的事
        Log.i(TAG, "--6--${Thread.currentThread().name}")
        return 29
    }
    //惰性启动
    fun onClickTest21(view: View){
        runBlocking<Unit> {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            val time = measureTimeMillis {
                Log.i(TAG, "--2--${Thread.currentThread().name}")
                val one = async(start = CoroutineStart.LAZY) { test21_1() }
                val two = async(start = CoroutineStart.LAZY) { test21_2() }
                // 执行一些计算
                one.start() // 启动第一个
                two.start() // 启动第二个
                Log.i(TAG, "--7--${one.await() + two.await()}--${Thread.currentThread().name}") //并发执行
            }
            Log.i(TAG, "--8--$time ms--${Thread.currentThread().name}")
        }
    }
    suspend fun test21_1(): Int {
        Log.i(TAG, "--3--${Thread.currentThread().name}")
        delay(1000L) // 假设我们在这里做了些有用的事
        Log.i(TAG, "--5--${Thread.currentThread().name}")
        return 13
    }

    suspend fun test21_2(): Int {
        Log.i(TAG, "--4--${Thread.currentThread().name}")
        delay(1000L) // 假设我们在这里也做了一些有用的事
        Log.i(TAG, "--6--${Thread.currentThread().name}")
        return 29
    }
    fun onClickTest22(view: View){
        runBlocking<Unit> {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            val time = measureTimeMillis {
                Log.i(TAG, "--2--${Thread.currentThread().name}")
                Log.i(TAG, "--8--${test22_Sum()}--${Thread.currentThread().name}")
            }
            Log.i(TAG, "--9--$time ms--${Thread.currentThread().name}")
        }
    }
    suspend fun test22_Sum(): Int = coroutineScope {
        Log.i(TAG, "--3--${Thread.currentThread().name}")
        val one = async { test22_1() }
        val two = async { test22_2() }
        one.await() + two.await()
    }

    suspend fun test22_1(): Int {
        Log.i(TAG, "--4--${Thread.currentThread().name}")
        delay(1000L) // 假设我们在这里做了些有用的事
        Log.i(TAG, "--6--${Thread.currentThread().name}")
        return 13
    }

    suspend fun test22_2(): Int {
        Log.i(TAG, "--5--${Thread.currentThread().name}")
        delay(1000L) // 假设我们在这里也做了一些有用的事
        Log.i(TAG, "--7--${Thread.currentThread().name}")
        return 29
    }

    fun onClickTest23(view: View) {
        runBlocking<Unit> {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            launch {
                // 运行在父协程的上下文中，即 runBlocking 主协程
                Log.i(TAG, "--6--${Thread.currentThread().name}")
            }
            launch(Dispatchers.Unconfined) {
                // 不受限的——将工作在主线程中
                Log.i(TAG, "--2--${Thread.currentThread().name}")
            }
            launch(Dispatchers.Main) {

                Log.i(TAG, "--8--${Thread.currentThread().name}")
            }
            launch(Dispatchers.IO) {

                Log.i(TAG, "--3--${Thread.currentThread().name}")
            }
            launch(Dispatchers.Default) {
                // 将会获取默认调度器
                Log.i(TAG, "--5--${Thread.currentThread().name}")
            }
            launch(newSingleThreadContext("MyOwnThread")) {
                // 将使它获得一个新的线程
                Log.i(TAG, "--7--${Thread.currentThread().name}")
            }
            Log.i(TAG, "--4--${Thread.currentThread().name}")
        }
    }
    //Dispatchers.Unconfined 非受限,当 delay 函数调用的时候，非受限的那个协程在默认的执行者线程中恢复执行。
    fun onClickTest24(view: View){
        runBlocking<Unit> {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            launch(Dispatchers.Unconfined) { // 非受限的——将和主线程一起工作
                Log.i(TAG, "--2--${Thread.currentThread().name}")
                delay(500)
                Log.i(TAG, "--5--${Thread.currentThread().name}") //非限制挂起后会改变线程
            }
            launch { // 父协程的上下文，主 runBlocking 协程
                Log.i(TAG, "--4--${Thread.currentThread().name}")
                delay(1000)
                Log.i(TAG, "--6--${Thread.currentThread().name}")
            }
            Log.i(TAG, "--3--${Thread.currentThread().name}")
        }
    }
    fun onClickTest25(view: View){
        runBlocking<Unit> {
            Log.i(TAG, "--1--${coroutineContext[Job]}--${Thread.currentThread().name}")
        }
    }
    fun onClickTest26(view: View){
        runBlocking<Unit> {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            // 启动一个协程来处理某种传入请求（request）
            val request = launch {
                Log.i(TAG, "--3--${Thread.currentThread().name}")
                // 孵化了两个子作业, 其中一个通过 GlobalScope 启动
                GlobalScope.launch {
                    Log.i(TAG, "--4--${Thread.currentThread().name}")
                    delay(1000)
                    Log.i(TAG, "--10--${Thread.currentThread().name}")
                }
                // 另一个则承袭了父协程的上下文
                launch {
                    Log.i(TAG, "--6--${Thread.currentThread().name}")
                    delay(100)
                    Log.i(TAG, "--7--${Thread.currentThread().name}")
                    delay(1000)
                    Log.i(TAG, "--不会执行--${Thread.currentThread().name}")
                }
                Log.i(TAG, "--5--${Thread.currentThread().name}")
            }
            Log.i(TAG, "--2--${Thread.currentThread().name}")
            delay(500)
            Log.i(TAG, "--8--${Thread.currentThread().name}")
            request.cancel() // 取消请求（request）的执行
            Log.i(TAG, "--9--${Thread.currentThread().name}")
            delay(1000) // 延迟一秒钟来看看发生了什么
            Log.i(TAG, "--11--${Thread.currentThread().name}")
        }
    }
    /*一个父协程总是等待所有的子协程执行结束。父协程并不显式的跟踪所有子协程的启动，并且不必使用 Job.join 在最后的时候等待它们*/
    fun onClickTest27(view: View){
        runBlocking<Unit> {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            // 启动一个协程来处理某种传入请求（request）
            val request = launch {
                Log.i(TAG, "--3--${Thread.currentThread().name}")
                repeat(3) { i -> // 启动少量的子作业
                    launch  {
                        Log.i(TAG, "--5--${i}--${Thread.currentThread().name}")
                        delay((i + 1) * 200L) // 延迟 200 毫秒、400 毫秒、600 毫秒的时间
                        Log.i(TAG, "--6--${i}--${Thread.currentThread().name}")
                    }
                }
                Log.i(TAG, "--4--${Thread.currentThread().name}")
            }
            Log.i(TAG, "--2--${Thread.currentThread().name}")
            request.join() // 等待请求的完成，包括其所有子协程, 注释这一句效果一样
            Log.i(TAG, "--7--${Thread.currentThread().name}")
        }
    }
    fun onClickTest28(view: View){
        runBlocking<Unit> {
            launch(Dispatchers.Default + CoroutineName("test")) {
                Log.i(TAG, "--1--${Thread.currentThread().name}")
            }
        }
    }
    fun onClickTest29(view: View){
        runBlocking<Unit> {
            test29().forEach { value -> Log.i(TAG, "--1--$value--${Thread.currentThread().name}") }
        }
    }
    suspend fun test29(): List<Int> {
        delay(1000) // 假装我们在这里做了一些异步的事情
        return listOf(1, 2, 3)
    }

    /*注意使用 Flow 的代码与先前示例的下述区别：

    名为 flow 的 Flow 类型构建器函数。
    flow { ... } 构建块中的代码可以挂起。
    函数 test30 不再标有 suspend 修饰符。
    流使用 emit 函数 发射 值。
    流使用 collect 函数 收集 值。*/
    fun onClickTest30(view: View){
        runBlocking<Unit> {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            // 启动并发的协程以验证主线程并未阻塞
            launch {
                for (k in 1..3) {
                    Log.i(TAG, "--4--$k--${Thread.currentThread().name}")
                    delay(100)
                    Log.i(TAG, "--7--$k--${Thread.currentThread().name}")
                }
            }
            Log.i(TAG, "--2--${Thread.currentThread().name}")
            // 收集这个流
            test30().collect { value -> Log.i(TAG, "--6--$value--${Thread.currentThread().name}") }
        }
    }
    fun test30(): Flow<Int> = flow { // 流构建器
        for (i in 1..3) {
            Log.i(TAG, "--3--$i--${Thread.currentThread().name}")
            delay(100) // 假装我们在这里做了一些有用的事情
            Log.i(TAG, "--5--$i--${Thread.currentThread().name}")
            emit(i) // 发送下一个值
        }
    }
    fun onClickTest31(view: View){
        runBlocking<Unit> {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            val flow = test31()
            Log.i(TAG, "--2--${Thread.currentThread().name}")
            flow.collect { value -> Log.i(TAG, "--6--$value--${Thread.currentThread().name}") }
            Log.i(TAG, "--7--${Thread.currentThread().name}")
            flow.collect { value -> Log.i(TAG, "--8--$value--${Thread.currentThread().name}") }
        }
    }

    fun test31(): Flow<Int> = flow {
        Log.i(TAG, "--3--${Thread.currentThread().name}")
        for (i in 1..3) {
            Log.i(TAG, "--4--$i--${Thread.currentThread().name}")
            delay(100)
            Log.i(TAG, "--5--$i--${Thread.currentThread().name}")
            emit(i)
        }
    }

    fun onClickTest32(view: View){
        runBlocking<Unit> {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            withTimeoutOrNull(250) { // 在 250 毫秒后超时
                Log.i(TAG, "--2--${Thread.currentThread().name}")
                test32().collect { value -> Log.i(TAG, "--5--$value--${Thread.currentThread().name}") }
            }
            Log.i(TAG, "--6--${Thread.currentThread().name}")
        }
    }
    fun test32(): Flow<Int> = flow {
        for (i in 1..3) {
            Log.i(TAG, "--3--$i--${Thread.currentThread().name}")
            delay(100)
            Log.i(TAG, "--4--$i--${Thread.currentThread().name}")
            emit(i)
        }
    }
    fun onClickTest33(view: View){
        runBlocking<Unit> {
            // 将一个整数区间转化为流
            (1..3).asFlow().collect { value -> Log.i(TAG, "--1--$value--${Thread.currentThread().name}")  }
        }
    }
    fun onClickTest34(view: View){
        runBlocking<Unit> {
            (1..3).asFlow() // 一个请求流
                .map { request -> test34(request) }
                .collect { response -> Log.i(TAG, "--1--$response--${Thread.currentThread().name}") }
        }
    }

    suspend fun test34(request: Int): String {
        delay(1000) // 模仿长时间运行的异步工作
        return "response $request"
    }

    fun onClickTest35(view: View){
        runBlocking<Unit> {
            (1..3).asFlow() // 一个请求流
                .transform { request ->
                    emit("Making request $request")
                    emit(test35(request))
                }
                .collect { response -> Log.i(TAG, "--1--$response--${Thread.currentThread().name}") }
        }
    }
    suspend fun test35(request: Int): String {
        delay(1000) // 模仿长时间运行的异步工作
        return "response $request"
    }
    //限长操作符
    fun onClickTest36(view: View){
        runBlocking<Unit> {
            test36()
                .take(2) // 只获取前两个
                .collect { value -> Log.i(TAG, "--2--$value--${Thread.currentThread().name}") }
        }
    }
    fun test36(): Flow<Int> = flow {
        try {
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            emit(1)
            Log.i(TAG, "--3--${Thread.currentThread().name}")
            emit(2)
            Log.i(TAG, "--不执行--${Thread.currentThread().name}")
            emit(3)
            Log.i(TAG, "--不执行--${Thread.currentThread().name}")
        } finally {
            Log.i(TAG, "--4--${Thread.currentThread().name}")
        }
    }
    fun onClickTest37(view: View){
        runBlocking<Unit> {
            val sum = (1..5).asFlow()
                .map { it * it } // 数字 1 至 5 的平方
                .reduce { a, b -> a + b } // 求和（末端操作符）
            Log.i(TAG, "--1--$sum--${Thread.currentThread().name}")
        }
    }
    fun onClickTest38(view: View){
        runBlocking<Unit> {
            (1..5).asFlow()
                .filter {
                    Log.i(TAG, "--1--$it--${Thread.currentThread().name}")
                    it % 2 == 0
                }
                .map {
                    Log.i(TAG, "--2--$it--${Thread.currentThread().name}")
                    "string $it"
                }.collect {
                    Log.i(TAG, "--3--$it--${Thread.currentThread().name}")
                }
        }
    }
    fun onClickTest39(view: View){
        runBlocking<Unit> {
            test39().collect { value -> Log.i(TAG, "--3--$value--${Thread.currentThread().name}") }
        }
    }
    fun test39(): Flow<Int> = flow {
        Log.i(TAG, "--1--${Thread.currentThread().name}")
        for (i in 1..3) {
            Log.i(TAG, "--2--$i--${Thread.currentThread().name}")
            emit(i)
        }
    }
    //切换线程
    fun onClickTest40(view: View){
        runBlocking<Unit> {
            test40().collect { value ->
                Log.i(TAG, "--4--$value--${Thread.currentThread().name}")
            }
        }
    }
    fun test40(): Flow<Int> = flow {
        Log.i(TAG, "--1--${Thread.currentThread().name}")
        for (i in 1..3) {
            Log.i(TAG, "--2--$i--${Thread.currentThread().name}")
            Thread.sleep(100) // 假装我们以消耗 CPU 的方式进行计算
            Log.i(TAG, "--3--$i--${Thread.currentThread().name}")
            emit(i) // 发射下一个值
        }
    }.flowOn(Dispatchers.Default) // 在流构建器中改变消耗 CPU 代码上下文的正确方式

    //串行运行
    fun onClickTest41(view: View){
        runBlocking<Unit> {
            val time = measureTimeMillis {
                test41().collect { value ->
                    Log.i(TAG, "--3--$value--${Thread.currentThread().name}")
                    delay(300) // 假装我们花费 300 毫秒来处理它
                    Log.i(TAG, "--4--$value--${Thread.currentThread().name}")
                }
            }
            Log.i(TAG, "--5--$time ms--${Thread.currentThread().name}")
        }
    }
    fun test41(): Flow<Int> = flow {
        for (i in 1..3) {
            Log.i(TAG, "--1--$i--${Thread.currentThread().name}")
            delay(100) // 假装我们异步等待了 100 毫秒
            Log.i(TAG, "--2--$i--${Thread.currentThread().name}")
            emit(i) // 发射下一个值
        }
    }
    //缓冲运行
    fun onClickTest42(view: View){
        runBlocking<Unit> {
            val time = measureTimeMillis {
                test42()
                    .buffer() // 缓冲发射项，无需等待
                    .collect { value ->
                        //Log.i(TAG, "--3--$value--${Thread.currentThread().name}")
                        delay(300) // 假装我们花费 300 毫秒来处理它
                        Log.i(TAG, "--4--$value--${Thread.currentThread().name}")
                    }
            }
            Log.i(TAG, "--5--$time ms--${Thread.currentThread().name}")
        }
    }

    fun test42(): Flow<Int> = flow {
        for (i in 1..3) {
            //Log.i(TAG, "--1--$i--${Thread.currentThread().name}")
            delay(100) // 假装我们异步等待了 100 毫秒
            Log.i(TAG, "--2--$i--${Thread.currentThread().name}")
            emit(i) // 发射下一个值
        }
    }
    //会丢掉某个值
    fun onClickTest43(view: View){
        runBlocking<Unit> {
            val time = measureTimeMillis {
                test43()
                    .conflate() // 合并发射项，不对每个值进行处理
                    .collect { value ->
                        //Log.i(TAG, "--3--$value--${Thread.currentThread().name}")
                        delay(300) // 假装我们花费 300 毫秒来处理它
                        Log.i(TAG, "--4--$value--${Thread.currentThread().name}")
                    }
            }
            Log.i(TAG, "--5--$time ms--${Thread.currentThread().name}")
        }
    }
    fun test43(): Flow<Int> = flow {
        for (i in 1..3) {
            //Log.i(TAG, "--1--$i--${Thread.currentThread().name}")
            delay(100) // 假装我们异步等待了 100 毫秒
            Log.i(TAG, "--2--$i--${Thread.currentThread().name}")
            emit(i) // 发射下一个值
        }
    }

    //只取最后一个值
    fun onClickTest44(view: View){
        runBlocking<Unit> {
            val time = measureTimeMillis {
                test44()
                    .collectLatest { value -> // 取消并重新发射最后一个值
                        //Log.i(TAG, "--3--$value--${Thread.currentThread().name}")
                        delay(300) // 假装我们花费 300 毫秒来处理它
                        Log.i(TAG, "--4--$value--${Thread.currentThread().name}")
                    }
            }
            Log.i(TAG, "--5--$time ms--${Thread.currentThread().name}")
        }
    }
    fun test44(): Flow<Int> = flow {
        for (i in 1..3) {
            //Log.i(TAG, "--1--$i--${Thread.currentThread().name}")
            delay(100) // 假装我们异步等待了 100 毫秒
            Log.i(TAG, "--2--$i--${Thread.currentThread().name}")
            emit(i) // 发射下一个值
        }
    }
    fun onClickTest45(view: View){
        runBlocking<Unit> {
            val nums = (1..3).asFlow() // 数字 1..3
            val strs = flowOf("one", "two", "three") // 字符串
            nums.zip(strs) { a, b -> "$a -> $b" } // 组合单个字符串
                .collect { Log.i(TAG, "--1--$it--${Thread.currentThread().name}") } // 收集并打印
        }
    }
    fun onClickTest46(view: View){
        runBlocking<Unit> {
            val nums = (1..3).asFlow().onEach { delay(300) } // 发射数字 1..3，间隔 300 毫秒
            val strs = flowOf("one", "two", "three").onEach { delay(400) } // 每 400 毫秒发射一次字符串
            val startTime = System.currentTimeMillis() // 记录开始的时间
            nums.zip(strs) { a, b -> "$a -> $b" } // 使用“zip”组合单个字符串
                .collect { value -> // 收集并打印
                    Log.i(TAG, "--1--$value--${System.currentTimeMillis() - startTime} ms--${Thread.currentThread().name}")
                }
        }
    }
    fun onClickTest47(view: View){
        runBlocking<Unit> {
            val nums = (1..3).asFlow().onEach { delay(300) } // 发射数字 1..3，间隔 300 毫秒
            val strs = flowOf("one", "two", "three").onEach { delay(400) } // 每 400 毫秒发射一次字符串
            val startTime = System.currentTimeMillis() // 记录开始的时间
            nums.combine(strs) { a, b -> "$a -> $b" } // 使用“combine”组合单个字符串
                .collect { value -> // 收集并打印
                    Log.i(TAG, "--1--$value--${System.currentTimeMillis() - startTime} ms--${Thread.currentThread().name}")
                }
        }
    }
    fun onClickTest48(view: View){
        runBlocking<Unit> {
            val startTime = System.currentTimeMillis() // 记录开始时间
            (1..3).asFlow().onEach { delay(100) } // 每 100 毫秒发射一个数字
                .flatMapConcat {
                    Log.i(TAG, "--1--$it--${Thread.currentThread().name}")
                    test48(it)
                }
                .collect { value -> // 收集并打印
                    Log.i(TAG, "--5--$value--${System.currentTimeMillis() - startTime}--${Thread.currentThread().name}")
                }
        }
    }
    fun test48(i: Int): Flow<String> = flow {
        Log.i(TAG, "--2--$i--${Thread.currentThread().name}")
        emit("$i: First")
        Log.i(TAG, "--3--$i--${Thread.currentThread().name}")
        delay(500) // 等待 500 毫秒
        Log.i(TAG, "--4--$i--${Thread.currentThread().name}")
        emit("$i: Second")
    }
    fun onClickTest49(view: View){
        runBlocking<Unit> {
            val startTime = System.currentTimeMillis() // 记录开始时间
            (1..3).asFlow().onEach { delay(100) } // 每 100 毫秒发射一个数字
                .flatMapMerge {
                    Log.i(TAG, "--1--$it--${Thread.currentThread().name}")
                    test49(it)
                }
                .collect { value -> // 收集并打印
                    Log.i(TAG, "--5--$value--${System.currentTimeMillis() - startTime}--${Thread.currentThread().name}")
                }
        }
    }
    fun test49(i: Int): Flow<String> = flow {
        Log.i(TAG, "--2--$i--${Thread.currentThread().name}")
        emit("$i: First")
        Log.i(TAG, "--3--$i--${Thread.currentThread().name}")
        delay(500) // 等待 500 毫秒
        Log.i(TAG, "--4--$i--${Thread.currentThread().name}")
        emit("$i: Second")
    }
    fun onClickTest50(view: View){
        runBlocking<Unit> {
            val startTime = System.currentTimeMillis() // 记录开始时间
            (1..3).asFlow().onEach { delay(100) } // 每 100 毫秒发射一个数字
                .flatMapLatest {
                    Log.i(TAG, "--1--$it--${Thread.currentThread().name}")
                    test50(it)
                }
                .collect { value -> // 收集并打印
                    Log.i(TAG, "--5--$value--${System.currentTimeMillis() - startTime}--${Thread.currentThread().name}")

                }
        }
    }
    fun test50(i: Int): Flow<String> = flow {
        Log.i(TAG, "--2--$i--${Thread.currentThread().name}")
        emit("$i: First")
        Log.i(TAG, "--3--$i--${Thread.currentThread().name}")
        delay(500) // 等待 500 毫秒
        Log.i(TAG, "--4--$i--${Thread.currentThread().name}")
        emit("$i: Second")
    }
    //异常流
    fun onClickTest51(view: View){
        runBlocking<Unit> {
            try {
                test51().collect { value ->
                    Log.i(TAG, "--2--$value--${Thread.currentThread().name}")
                    check(value <= 1) { "Collected $value" }
                }
            } catch (e: Throwable) {
                Log.i(TAG, "--3--$e--${Thread.currentThread().name}")
            }
        }
    }
    fun test51(): Flow<Int> = flow {
        for (i in 1..3) {
            Log.i(TAG, "--1--$i--${Thread.currentThread().name}")
            emit(i) // 发射下一个值
        }
    }
    fun onClickTest52(view: View){
        runBlocking<Unit> {
            try {
                test52().collect { value -> Log.i(TAG, "--4--$value--${Thread.currentThread().name}") }
            } catch (e: Throwable) {
                Log.i(TAG, "--5--$e--${Thread.currentThread().name}")
            }
        }
    }
    fun test52(): Flow<String> =
        flow {
            for (i in 1..3) {
                Log.i(TAG, "--1--$i--${Thread.currentThread().name}")
                emit(i) // 发射下一个值
            }
        }
            .map { value ->
                Log.i(TAG, "--2--$value--${Thread.currentThread().name}")
                check(value <= 1) { "Crashed on $value" }
                Log.i(TAG, "--3--$value--${Thread.currentThread().name}")
                "string $value"
            }
    fun onClickTest53(view: View){
        runBlocking<Unit> {
            test53()
                .catch { e ->
                    Log.i(TAG, "--5--$e--${Thread.currentThread().name}")
                    emit("Caught $e")
                } // 发射一个异常
                .collect { value -> Log.i(TAG, "--4--$value--${Thread.currentThread().name}") }
        }
    }
    fun test53(): Flow<String> =
        flow {
            for (i in 1..3) {
                Log.i(TAG, "--1--$i--${Thread.currentThread().name}")
                emit(i) // 发射下一个值
            }
        }
            .map { value ->
                Log.i(TAG, "--2--$value--${Thread.currentThread().name}")
                check(value <= 1) { "Crashed on $value" }
                Log.i(TAG, "--3--$value--${Thread.currentThread().name}")
                "string $value"
            }
    //捕获异常出错
    fun onClickTest54(view: View){
        runBlocking<Unit> {
            test54()
                .catch { e -> Log.i(TAG, "--4--$e--${Thread.currentThread().name}") } // 不会捕获下游异常
                .collect { value ->
                    Log.i(TAG, "--2--$value--${Thread.currentThread().name}")
                    check(value <= 1) { "Collected $value" }
                    Log.i(TAG, "--3--$value--${Thread.currentThread().name}")
                }
        }
    }
    fun test54(): Flow<Int> = flow {
        for (i in 1..3) {
            Log.i(TAG, "--1--$i--${Thread.currentThread().name}")
            emit(i)
        }
    }
    fun onClickTest55(view: View){
        runBlocking<Unit> {
            test55()
                .onEach { value ->
                    Log.i(TAG, "--2--$value--${Thread.currentThread().name}")
                    check(value <= 1) { "Collected $value" }
                    Log.i(TAG, "--3--$value--${Thread.currentThread().name}")
                }
                .catch { e -> Log.i(TAG, "--4--$e--${Thread.currentThread().name}") }
                .collect()
        }
    }
    fun test55(): Flow<Int> = flow {
        for (i in 1..3) {
            Log.i(TAG, "--1--$i--${Thread.currentThread().name}")
            emit(i)
        }
    }
    fun onClickTest56(view: View){
        runBlocking<Unit> {
            try {
                test56().collect { value -> Log.i(TAG, "--1--$value--${Thread.currentThread().name}") }
            } finally {
                Log.i(TAG, "--2--${Thread.currentThread().name}")
            }
        }
    }
    fun test56(): Flow<Int> = (1..3).asFlow()
    fun onClickTest57(view: View){
        runBlocking<Unit> {
            test57()
                .onCompletion { Log.i(TAG, "--2--${Thread.currentThread().name}") }
                .collect { value -> Log.i(TAG, "--1--$value--${Thread.currentThread().name}") }
        }
    }
    fun test57(): Flow<Int> = (1..3).asFlow()
    fun onClickTest58(view: View){
        runBlocking<Unit> {
            test58()
                .onCompletion { cause -> if (cause != null){
                    Log.i(TAG, "--3--$cause--${Thread.currentThread().name}")
                }else{
                    Log.i(TAG, "--4--$cause--${Thread.currentThread().name}")
                } }
                .catch { cause -> Log.i(TAG, "--5--$cause--${Thread.currentThread().name}") }
                .collect { value ->Log.i(TAG, "--2--$value--${Thread.currentThread().name}") }
        }
    }
    fun test58(): Flow<Int> = flow {
        Log.i(TAG, "--1--${Thread.currentThread().name}")
        emit(1)
        throw RuntimeException()
    }
    fun onClickTest59(view: View){
        runBlocking<Unit> {
            test59()
                .onCompletion { cause -> Log.i(TAG, "--3--$cause--${Thread.currentThread().name}") }
                .catch { cause -> Log.i(TAG, "--4--$cause--${Thread.currentThread().name}") }
                .collect { value ->
                    Log.i(TAG, "--1--$value--${Thread.currentThread().name}")
                    check(value <= 1) { "Collected $value" }
                    Log.i(TAG, "--2--$value--${Thread.currentThread().name}")
                }
        }
    }
    fun test59(): Flow<Int> = (1..3).asFlow()
    fun onClickTest60(view: View){
        runBlocking<Unit> {
            test60()
                .onEach { value ->
                    Log.i(TAG, "--1--$value--${Thread.currentThread().name}")
                    check(value <= 1) { "Collected $value" }
                    Log.i(TAG, "--2--$value--${Thread.currentThread().name}")
                }
                .onCompletion { cause -> Log.i(TAG, "--3--$cause--${Thread.currentThread().name}") }
                .catch { cause -> Log.i(TAG, "--4--$cause--${Thread.currentThread().name}") }
                .collect();
        }
    }
    fun test60(): Flow<Int> = (1..3).asFlow()
    fun onClickTest61(view: View){
        runBlocking<Unit> {
            test61()
                .onEach { event -> Log.i(TAG, "--3--$event--${Thread.currentThread().name}") }
                .collect() // <--- 等待流收集
            Log.i(TAG, "--4--${Thread.currentThread().name}")
        }
    }
    fun test61(): Flow<Int> = (1..3).asFlow().onEach {
        Log.i(TAG, "--1--$it--${Thread.currentThread().name}")
        delay(100)
        Log.i(TAG, "--2--$it--${Thread.currentThread().name}")
    }
    fun onClickTest62(view: View){
        runBlocking<Unit> {
            test62()
                .onEach { event -> Log.i(TAG, "--3--$event--${Thread.currentThread().name}") }
                .launchIn(this) // <--- 在单独的协程中执行流， this指的是协程
            Log.i(TAG, "--4--${Thread.currentThread().name}")
        }
    }
    fun test62(): Flow<Int> = (1..3).asFlow().onEach {
        Log.i(TAG, "--1--$it--${Thread.currentThread().name}")
        delay(100)
        Log.i(TAG, "--2--$it--${Thread.currentThread().name}")
    }
    fun onClickTest63(view: View){
        runBlocking<Unit> {
            test63().collect { value ->
                Log.i(TAG, "--2--$value--${Thread.currentThread().name}")
                if (value == 3) cancel()
                Log.i(TAG, "--3--$value--${Thread.currentThread().name}")
            }
        }
    }
    fun test63(): Flow<Int> = flow {
        for (i in 1..5) {
            Log.i(TAG, "--1--$i--${Thread.currentThread().name}")
            emit(i)
        }
    }
    fun onClickTest64(view: View){
        runBlocking<Unit> {
            (1..5).asFlow().collect { value ->
                Log.i(TAG, "--1--$value--${Thread.currentThread().name}")
                if (value == 3) cancel()
                Log.i(TAG, "--2--$value--${Thread.currentThread().name}")
            }
        }
    }
    fun onClickTest65(view: View){
        runBlocking<Unit> {
            (1..5).asFlow().cancellable().collect { value ->
                Log.i(TAG, "--1--$value--${Thread.currentThread().name}")
                if (value == 3) cancel()
                Log.i(TAG, "--2--$value--${Thread.currentThread().name}")
            }
        }
    }
    fun onClickTest66(view: View){
        runBlocking {
            val channel = Channel<Int>()
            launch {
                // 这里可能是消耗大量 CPU 运算的异步逻辑，我们将仅仅做 5 次整数的平方并发送
                for (x in 1..5){
                    Log.i(TAG, "--1--$x--${Thread.currentThread().name}")
                    channel.send(x * x)
                }
            }
            // 这里我们打印了 5 次被接收的整数：
            repeat(5) {Log.i(TAG, "--2--${channel.receive()}--${Thread.currentThread().name}")}
            Log.i(TAG, "--3--${Thread.currentThread().name}")
        }
    }
    fun onClickTest67(view: View){
        runBlocking {
            val channel = Channel<Int>()
            launch {
                for (x in 1..5){
                    Log.i(TAG, "--1--$x--${Thread.currentThread().name}")
                    channel.send(x * x)
                }
                Log.i(TAG, "--2--${Thread.currentThread().name}")
                channel.close() // 我们结束发送
            }
            // 这里我们使用 `for` 循环来打印所有被接收到的元素（直到通道被关闭）
            for (y in channel) Log.i(TAG, "--3--$y--${Thread.currentThread().name}")
            Log.i(TAG, "--4--${Thread.currentThread().name}")
        }
    }
    fun onClickTest68(view: View){
        runBlocking {
            val squares = test68()
            squares.consumeEach { Log.i(TAG, "--1--$it--${Thread.currentThread().name}") }
            Log.i(TAG, "--2--${Thread.currentThread().name}")
        }
    }

    fun CoroutineScope.test68(): ReceiveChannel<Int> = produce {
        for (x in 1..5) send(x * x)
    }
    //管道是一种一个协程在流中开始生产可能无穷多个元素的模式：
    fun onClickTest69(view: View){
        runBlocking {
            val numbers = test69_1() // 从 1 开始生成整数
            val squares = test69_2(numbers) // 整数求平方
            repeat(5) {
                Log.i(TAG, "--1--${squares.receive()}--${Thread.currentThread().name}") // 输出前五个
            }
            Log.i(TAG, "--2--${Thread.currentThread().name}") // 至此已完成
            coroutineContext.cancelChildren() // 取消子协程
        }
    }
    fun CoroutineScope.test69_1() = produce<Int> {
        var x = 1
        while (true) send(x++) // 从 1 开始的无限的整数流
    }

    fun CoroutineScope.test69_2(numbers: ReceiveChannel<Int>): ReceiveChannel<Int> = produce {
        for (x in numbers) send(x * x)
    }
    //素数
    fun onClickTest70(view: View){
        runBlocking {
            var cur = test70_1(2)
            repeat(10) {
                val prime = cur.receive()
                Log.i(TAG, "--1--${prime}--${Thread.currentThread().name}")
                cur = test70_2(cur, prime)
            }
            coroutineContext.cancelChildren() // 取消所有的子协程来让主协程结束
        }
    }
    fun CoroutineScope.test70_1(start: Int) = produce<Int> {
        var x = start
        while (true) send(x++) // 从 start 开始过滤整数流
    }

    fun CoroutineScope.test70_2(numbers: ReceiveChannel<Int>, prime: Int) = produce<Int> {
        for (x in numbers) if (x % prime != 0) send(x)
    }
    fun onClickTest71(view: View){
        runBlocking<Unit> {
            val producer = test71_1()
            repeat(5) { test71_2(it, producer) }
            delay(950)
            producer.cancel() // 取消协程生产者从而将它们全部杀死
        }
    }
    fun CoroutineScope.test71_1() = produce<Int> {
        var x = 1 // start from 1
        while (true) {
            send(x++) // 产生下一个数字
            delay(100) // 等待 0.1 秒
        }
    }

    fun CoroutineScope.test71_2(id: Int, channel: ReceiveChannel<Int>) = launch {
        for (msg in channel) {
            Log.i(TAG, "--1--${id}--$msg--${Thread.currentThread().name}")
        }
    }
    fun onClickTest72(view: View){
        runBlocking {
            val channel = Channel<String>()
            launch { test72(channel, "foo", 200L) }
            launch { test72(channel, "BAR!", 500L) }
            repeat(6) { // 接收前六个
                Log.i(TAG, "--1--${channel.receive()}--${Thread.currentThread().name}")
            }
            coroutineContext.cancelChildren() // 取消所有子协程来让主协程结束
        }
    }
    suspend fun test72(channel: SendChannel<String>, s: String, time: Long) {
        while (true) {
            delay(time)
            channel.send(s)
        }
    }
    fun onClickTest73(view: View){
        runBlocking<Unit> {
            val channel = Channel<Int>(4) // 启动带缓冲的通道
            val sender = launch { // 启动发送者协程
                repeat(10) {
                    Log.i(TAG, "--1--${it}--${Thread.currentThread().name}") // 在每一个元素发送前打印它们
                    channel.send(it) // 将在缓冲区被占满时挂起
                }
            }
            // 没有接收到东西……只是等待……
            delay(1000)
            repeat(10) {
                Log.i(TAG, "--2--${channel.receive()}--${Thread.currentThread().name}")
            }
            sender.cancel() // 取消发送者协程
        }
    }
    fun onClickTest74(view: View){
        runBlocking {
            /*val job = GlobalScope.launch { // launch 根协程
                Log.i(TAG, "--2--${Thread.currentThread().name}")
                throw IndexOutOfBoundsException() // 我们将在控制台打印 Thread.defaultUncaughtExceptionHandler
            }
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            job.join()
            Log.i(TAG, "--不会打印--${Thread.currentThread().name}")*/
            val deferred = GlobalScope.async { // async 根协程
                Log.i(TAG, "--5--${Thread.currentThread().name}")
                throw ArithmeticException() // 没有打印任何东西，依赖用户去调用等待
            }
            try {
                Log.i(TAG, "--4--${Thread.currentThread().name}")
                deferred.await()
                Log.i(TAG, "--不会打印--${Thread.currentThread().name}")
            } catch (e: ArithmeticException) {
                Log.i(TAG, "--7--$e--${Thread.currentThread().name}")
            }
        }
    }

    fun onClickTest75(view: View){
        runBlocking {
            val handler = CoroutineExceptionHandler { _, exception ->
                Log.i(TAG, "--3--$exception--${Thread.currentThread().name}")
            }
            val job = GlobalScope.launch(handler) { // 根协程，运行在 GlobalScope 中
                Log.i(TAG, "--1--${Thread.currentThread().name}")
                throw AssertionError()
            }
            val deferred = GlobalScope.async(handler) { // 同样是根协程，但使用 async 代替了 launch
                Log.i(TAG, "--4--${Thread.currentThread().name}")
                throw ArithmeticException() // 没有打印任何东西，依赖用户去调用 deferred.await()
            }
            Log.i(TAG, "--2--${Thread.currentThread().name}")
            joinAll(job, deferred)
        }
    }
    fun onClickTest76(view: View){
        runBlocking {
            val job = launch {
                val child = launch {
                    try {
                        Log.i(TAG, "--3--${Thread.currentThread().name}")
                        delay(Long.MAX_VALUE)
                    } finally {
                        Log.i(TAG, "--6--${Thread.currentThread().name}")
                    }
                }
                Log.i(TAG, "--2--${Thread.currentThread().name}")
                yield()
                Log.i(TAG, "--4--${Thread.currentThread().name}")
                child.cancel()
                Log.i(TAG, "--5--${Thread.currentThread().name}")
                child.join()
                Log.i(TAG, "--7--${Thread.currentThread().name}")
                yield()
                Log.i(TAG, "--8--${Thread.currentThread().name}")
            }
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            job.join()
        }
    }
    fun onClickTest77(view: View){
        runBlocking {
            val handler = CoroutineExceptionHandler { _, exception ->
                Log.i(TAG, "--8--$exception--${Thread.currentThread().name}")
            }
            val job = GlobalScope.launch(handler) {
                launch { // 第一个子协程
                    try {
                        Log.i(TAG, "--2--${Thread.currentThread().name}")
                        delay(Long.MAX_VALUE)
                        Log.i(TAG, "--不执行--${Thread.currentThread().name}")
                    } finally {
                        withContext(NonCancellable) {
                            Log.i(TAG, "--6--${Thread.currentThread().name}")
                            delay(100)
                            Log.i(TAG, "--7--${Thread.currentThread().name}")
                        }
                    }
                }
                launch { // 第二个子协程
                    Log.i(TAG, "--3--${Thread.currentThread().name}")
                    delay(10)
                    Log.i(TAG, "--4--${Thread.currentThread().name}")
                    throw ArithmeticException()
                }
            }
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            job.join()
            Log.i(TAG, "--9--${Thread.currentThread().name}")
        }
    }
    fun onClickTest78(view: View){
        runBlocking {
            val handler = CoroutineExceptionHandler { _, exception ->
                Log.i(TAG, "--6--$exception--${exception.suppressed.contentToString()}--${Thread.currentThread().name}")
            }
            val job = GlobalScope.launch(handler) {
                launch {
                    try {
                        Log.i(TAG, "--2--${Thread.currentThread().name}")
                        delay(Long.MAX_VALUE) // 当另一个同级的协程因 IOException  失败时，它将被取消
                        Log.i(TAG, "--不执行--${Thread.currentThread().name}")
                    } finally {
                        throw ArithmeticException() // 第二个异常
                    }
                }
                launch {
                    Log.i(TAG, "--4--${Thread.currentThread().name}")
                    delay(100)
                    Log.i(TAG, "--5--${Thread.currentThread().name}")
                    throw IOException() // 首个异常
                }
                Log.i(TAG, "--3--${Thread.currentThread().name}")
                delay(Long.MAX_VALUE)
                Log.i(TAG, "--不执行--${Thread.currentThread().name}")
            }
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            job.join()
            Log.i(TAG, "--7--${Thread.currentThread().name}")
        }
    }
    fun onClickTest79(view: View){
        runBlocking {
            val handler = CoroutineExceptionHandler { _, exception ->
                Log.i(TAG, "--5--$exception--${Thread.currentThread().name}")
            }
            val job = GlobalScope.launch(handler) {
                val inner = launch { // 该栈内的协程都将被取消
                    launch {
                        launch {
                            Log.i(TAG, "--3--${Thread.currentThread().name}")
                            throw IOException() // 原始异常
                        }
                    }
                }
                try {
                    Log.i(TAG, "--2--${Thread.currentThread().name}")
                    inner.join()
                    Log.i(TAG, "--不执行--${Thread.currentThread().name}")
                } catch (e: CancellationException) {
                    Log.i(TAG, "--4--$e--${Thread.currentThread().name}")
                    throw e // 取消异常被重新抛出，但原始 IOException 得到了处理
                }
            }
            Log.i(TAG, "--1--${Thread.currentThread().name}")
            job.join()
            Log.i(TAG, "--7--${Thread.currentThread().name}")
        }
    }
    fun onClickTest80(view: View){
        runBlocking {
            val supervisor = SupervisorJob()
            with(CoroutineScope(coroutineContext + supervisor)) {
                // 启动第一个子作业——这个示例将会忽略它的异常（不要在实践中这么做！）
                val firstChild = launch(CoroutineExceptionHandler { _, _ ->  }) {
                    Log.i(TAG, "--2--${Thread.currentThread().name}")
                    throw AssertionError("The first child is cancelled")
                }
                // 启动第二个子作业
                val secondChild = launch {
                    Log.i(TAG, "--3--${Thread.currentThread().name}")
                    firstChild.join()
                    // 取消了第一个子作业且没有传播给第二个子作业
                    Log.i(TAG, "--4--${firstChild.isCancelled}--${Thread.currentThread().name}")
                    try {
                        Log.i(TAG, "--5--${Thread.currentThread().name}")
                        delay(Long.MAX_VALUE)
                        Log.i(TAG, "--不执行--${Thread.currentThread().name}")
                    } finally {
                        // 但是取消了监督的传播
                        Log.i(TAG, "--9--${Thread.currentThread().name}")
                    }
                }
                // 等待直到第一个子作业失败且执行完成
                Log.i(TAG, "--1--${Thread.currentThread().name}")
                firstChild.join()
                Log.i(TAG, "--6--${Thread.currentThread().name}")
                supervisor.cancel()
                Log.i(TAG, "--8--${Thread.currentThread().name}")
                secondChild.join()
                Log.i(TAG, "--10--${Thread.currentThread().name}")
            }
        }
    }
    fun onClickTest81(view: View){
        runBlocking {
            try {
                supervisorScope {
                    val child = launch {
                        try {
                            Log.i(TAG, "--2--${Thread.currentThread().name}")
                            delay(Long.MAX_VALUE)
                            Log.i(TAG, "--6--${Thread.currentThread().name}")
                        } finally {
                            Log.i(TAG, "--4--${Thread.currentThread().name}")
                        }
                    }
                    // 使用 yield 来给我们的子作业一个机会来执行打印
                    Log.i(TAG, "--1--${Thread.currentThread().name}")
                    yield()
                    Log.i(TAG, "--3--${Thread.currentThread().name}")
                    throw AssertionError()
                }
            } catch(e: AssertionError) {
                Log.i(TAG, "--5--${Thread.currentThread().name}")
            }
        }
    }
    fun onClickTest82(view: View){
        runBlocking {
            val handler = CoroutineExceptionHandler { _, exception ->
                Log.i(TAG, "--3--$exception--${Thread.currentThread().name}")
            }
            supervisorScope {
                val child = launch(handler) {
                    Log.i(TAG, "--2--${Thread.currentThread().name}")
                    throw AssertionError()
                }
                Log.i(TAG, "--1--${Thread.currentThread().name}")
            }
            Log.i(TAG, "--4--${Thread.currentThread().name}")
        }
    }
    suspend fun massiveRun(action: suspend () -> Unit) {
        val n = 100  // 启动的协程数量
        val k = 1000 // 每个协程重复执行同一动作的次数
        val time = measureTimeMillis {
            coroutineScope { // 协程的作用域
                repeat(n) {
                    launch {
                        repeat(k) { action() }
                    }
                }
            }
        }
        Log.i(TAG, "--1--${n * k} actions--$time ms--${Thread.currentThread().name}")
    }

    var counter1 = 0
    fun onClickTest83(view: View){
        runBlocking {
            withContext(Dispatchers.Default) {
                massiveRun {
                    counter1++
                }
            }
            Log.i(TAG, "--2--${counter1}--${Thread.currentThread().name}")
        }
    }

    @Volatile // 在 Kotlin 中 `volatile` 是一个注解
    var counter2 = 0
    fun onClickTest84(view: View){
        runBlocking {
            withContext(Dispatchers.Default) {
                massiveRun {
                    counter2++
                }
            }
            Log.i(TAG, "--2--${counter2}--${Thread.currentThread().name}")
        }
    }
    val counter3 = AtomicInteger()
    fun onClickTest85(view: View){
        runBlocking {
            withContext(Dispatchers.Default) {
                massiveRun {
                    counter3.incrementAndGet()
                }
            }
            Log.i(TAG, "--2--${counter3}--${Thread.currentThread().name}")
        }
    }
    val counterContext4 = newSingleThreadContext("CounterContext4")
    var counter4 = 0
    fun onClickTest86(view: View){
        runBlocking {
            withContext(Dispatchers.Default) {
                massiveRun {
                    // 将每次自增限制在单线程上下文中
                    withContext(counterContext4) {
                        counter4++
                    }
                }
            }
            Log.i(TAG, "--2--${counter4}--${Thread.currentThread().name}")
        }
    }
    val counterContext5 = newSingleThreadContext("CounterContext5")
    var counter5 = 0
    fun onClickTest87(view: View){
        runBlocking {
            // 将一切都限制在单线程上下文中
            withContext(counterContext5) {
                massiveRun {
                    counter5++
                }
            }
            Log.i(TAG, "--2--${counter5}--${Thread.currentThread().name}")
        }
    }
    val mutex6 = Mutex()
    var counter6 = 0
    fun onClickTest88(view: View){
        runBlocking {
            withContext(Dispatchers.Default) {
                massiveRun {
                    // 用锁保护每次自增
                    mutex6.withLock {
                        counter6++
                    }
                }
            }
            Log.i(TAG, "--2--${counter6}--${Thread.currentThread().name}")
        }
    }

    // 这个函数启动一个新的计数器 actor
    fun CoroutineScope.counterActor() = actor<CounterMsg> {
        var counter = 0 // actor 状态
        for (msg in channel) { // 即将到来消息的迭代器
            when (msg) {
                is IncCounter -> counter++
                is GetCounter -> msg.response.complete(counter)
            }
        }
    }

    fun onClickTest89(view: View){
        runBlocking<Unit> {
            val counter = counterActor() // 创建该 actor
            withContext(Dispatchers.Default) {
                massiveRun {
                    counter.send(IncCounter)
                }
            }
            // 发送一条消息以用来从一个 actor 中获取计数值
            val response = CompletableDeferred<Int>()
            counter.send(GetCounter(response))
            Log.i(TAG, "--2--${response.await()}--${Thread.currentThread().name}")
            counter.close() // 关闭该actor
        }
    }
    fun onClickTest90(view: View){}
    fun onClickTest91(view: View){}
    fun onClickTest92(view: View){}
    fun onClickTest93(view: View){}
    fun onClickTest94(view: View){}
    fun onClickTest95(view: View){}
    fun onClickTest96(view: View){}
    fun onClickTest97(view: View){}
    fun onClickTest98(view: View){}
    fun onClickTest99(view: View){}
    fun onClickTest100(view: View){}
}

// 计数器 Actor 的各种类型
sealed class CounterMsg
object IncCounter : CounterMsg() // 递增计数器的单向消息
class GetCounter(val response: CompletableDeferred<Int>) : CounterMsg() // 携带回复的请求
